package com.icas.util.shiro;

import com.icas.entity.databaseentity.AccountEntity;
import com.icas.service.AccountService;
import com.icas.util.jwt.JwtToken;
import com.icas.util.jwt.JwtUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.ObjectUtils;

/**
 * @Author: tocchen
 * @Date: 2022/4/18 18:01
 * @Description:
 **/
public class JwtRealm extends AuthorizingRealm {

    /**
     * 重定义token类型
     * @param token token
     * @return 布尔值
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 实现Shiro授权
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) throws AuthenticationException {
        String token = (String) principals.getPrimaryPrincipal();
        String id = JwtUtils.getId(token);
        AccountEntity accountEntity = AccountService.defaultUserServer.byIdGetInfo(id);

        if (ObjectUtils.isEmpty(accountEntity)){
            throw new AuthenticationException("无法获取token所携带的id值");
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRole(accountEntity.getRole());

        return info;
    }

    /**
     * 实现Shiro认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String jwt= (String) token.getCredentials();
        String username= null;
        //decode时候出错，可能是token的长度和规定好的不一样了
        try {
            username= JwtUtils.getAccount(jwt);
        }catch (Exception e){
            throw new AuthenticationException("token非法，不是规范的token，可能被篡改了，或者过期了");
        }

        if (!JwtUtils.verify(jwt)||username==null){
            throw new AuthenticationException("token认证失效，token错误或者过期，重新登陆");
        }


        AccountEntity user = AccountService.defaultUserServer.byAccountGetInfo(username);
        if (ObjectUtils.isEmpty(user)){
            throw new AuthenticationException("该用户不存在");
        }

        // 验证Token即可
        return new SimpleAuthenticationInfo(jwt,jwt,this.getName());
    }
}
